package spring.fox.context;

import fox.framework.rpc.client.invocation.proxy.RpcProxyFactory;
import fox.framework.rpc.context.AbstractRpcApplicationContext;
import fox.framework.rpc.context.ConfigurableRegisteredRpcObjectFactory;
import fox.framework.rpc.context.RpcApplicationConfigurer;
import fox.framework.rpc.context.RpcDefinitionRegister;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;

/**
 * @author cuichao
 * @Description: SpringFoxRpcApplicationContext
 * @Date: create in 2021/3/9 23:18
 */
public class SpringFoxRpcApplicationContext extends AbstractRpcApplicationContext implements BeanFactoryAware {

    private final RpcApplicationConfigurer configurer;

    private ConfigurableListableBeanFactory beanFactory;

    private volatile ConfigurableRegisteredRpcObjectFactory objectFactory;


    public SpringFoxRpcApplicationContext(RpcApplicationConfigurer configurer) {
        this.configurer = configurer;
    }


    public RpcProxyFactory getProxyFactory(){
        return super.getGlobalProxyFactory();
    }


    @Override
    protected RpcApplicationConfigurer getRpcApplicationConfigure() {
        return configurer;
    }

    @Override
    protected RpcDefinitionRegister getRpcDefinitionRegister() {
        synchronized (this) {
            if (this.objectFactory == null) {
                this.objectFactory = new SpringFoxRpcObjectFactory(this.beanFactory);
            }
            return this.objectFactory;
        }
    }

    @Override
    public ConfigurableRegisteredRpcObjectFactory getObjectFactory() {
        synchronized (this) {
            if (this.objectFactory == null) {
                this.objectFactory = new SpringFoxRpcObjectFactory(this.beanFactory);
            }
            return this.objectFactory;
        }
    }


    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
            throw new IllegalArgumentException(
                    this.getClass().getSimpleName() + " requires a ConfigurableListableBeanFactory: " + beanFactory);
        }
        if (!(beanFactory instanceof BeanDefinitionRegistry)) {
            throw new IllegalStateException(this.getClass().getSimpleName() + ": Could not locate BeanDefinitionRegistry");
        }
        this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
    }
}
